% +------------------------+
% | Jeff Ahern & Kevin Gin |
% | CSC 372                |
% | Homework 6             |
% +------------------------+


% vowel  -- 1 or more vowels
% cons0  -- 0 or more consonants
% cons1  -- 1 consonant
% consV  -- 1 voiced consonant
% suffix -- 
% vowelF -- Front vowel
% any    -- anything
% none   -- nothing

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                            Letter qualities
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Vowels: One or more vowels (A, O, U, E, I, Ya)
vowel(A) :- A = 'a'.
vowel(A) :- A = 'e'.
vowel(A) :- A = 'i'.
vowel(A) :- A = 'o'.
vowel(A) :- A = 'u'.
vowel(A) :-    A = 'y'.

% Front Vowels: One of E, I or Y (a front vowel)
vowelF(A) :- A = 'e'.
vowelF(A) :- A = 'i'.
vowelF(A) :- A = 'y'.

% Consonants: (B, C, D, F, G, H, J, K, L, M, N, P, Q, R, S, T, V, W, X, Z)
cons(A) :- \+(vowel(A)).

%  Voiced Consonants: One voiced consonant (B, D, V, G, J, L, M, N, R, W or Z)
consV(A) :- A = 'b'.
consV(A) :- A = 'd'.
consV(A) :- A = 'v'.
consV(A) :- A = 'g'.
consV(A) :- A = 'j'.
consV(A) :- A = 'l'.
consV(A) :- A = 'm'.
consV(A) :- A = 'n'.
consV(A) :- A = 'r'.
consV(A) :- A = 'w'.
consV(A) :- A = 'z'.

% Suffix: One of ER, E, ES, ED, ING, ELY (a suffix) (right context only)
suffix([H|T]) :-
    H = e,
    T = [M|_],
    M = r,!.
    
suffix([H|T]) :-
    H = e,
    length(T,0),!.

suffix([H|T]) :-
    H = e,
    T = [M|_],
    M = s,!.

suffix([H|T]) :-
    H = e,
    T = [M|_],
    M = d,!.

suffix([H|T]) :-
    H = i,
    T = [M|N],
    M = n,
    N = [I|_],
    I = g,!.

suffix([H|T]) :-
    H = e,
    T = [M|N],
    M = l,
    N = [I|_],
    I = y,!.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                            prefix match
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



% ===== One or more vowels ==========
prefix_match([], _).
prefix_match([vowel|B], [H|T]) :-    
    vowel(H),
    prefix_match([vowel|B], T).
prefix_match([vowel|B], [H|T]) :-    
    vowel(H),
    prefix_match(B, T).

% ===== Zero or more consonants =====
prefix_match([cons0|B], [H|T]) :-    
    cons(H),
    prefix_match([cons0|B], T).
prefix_match([cons0|B], [H|T]) :-    
    cons(H),
    prefix_match(B, T).
prefix_match([cons0|B], [H|T]) :-    
    vowel(H),
    prefix_match([cons0|B], T).
prefix_match([cons0|B], [H|T]) :-    
    vowel(H),
    prefix_match(B, T).

% ===== One consonant ===============
prefix_match([cons1|B], [H|T]) :-        
    cons(H),
    prefix_match(B, T).

% ===== One voiced consonant ========
prefix_match([consV|B], [H|T]) :-
    consV(H),
    prefix_match(B, T).

% ===== One front vowel =============
prefix_match([front|B], [H|T]) :-
    vowelF(H),
    prefix_match(B, T).

% ===== Common suffixes =============

prefix_match([suffix|B], Chars) :-    
    suffix(Chars),
    prefix_match(B, Chars).

prefix_match([suffix|B], [_|T]) :-    
    suffix([T]),
    prefix_match([suffix|B], [T]).

prefix_match([suffix|_], [H|_]) :-
    suffix([H]).

prefix_match(_,_) :-
    fail.


% ===== One letter ==================    ********* TO-DO *********

% ===== End of the context ==========    ********* TO-DO *********

p1 :- prefix_match([vowel],[a]).  % yes
p2 :- prefix_match([vowel],[a,a,a]). % yes
p3 :- prefix_match([vowel,cons1],[a,b]). % yes
p4 :- prefix_match([vowel,cons1],[a,e]). % no
p5 :- prefix_match([vowel,cons1,vowel],[a,l,e]). % yes

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                            suffix match
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


suffix_match([A|B], [H|T]) :-
    reverse([A|B], X),    
    reverse([H|T], Y),
    prefix_match(X, Y),!.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                            Matching
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
match(Chars, Phonemes, Rules) :- 
    matchhelp(Chars,A, B,_,Chars),
    phonemeshelp(A,_,Z),
    Phonemes = Z,
    Rules = B.

phonemeshelp([],X,X).
    
phonemeshelp([H|T],Final,T1):-
    append(Final,H,Final2),
    phonemeshelp(T,Final2,T1),!.

startswith([],[]).
startswith([],_).
startswith([H|T],[H1|T1]):-
    H = H1,
    startswith(T,T1).
    
matchhelp([],[],[],[],_).    

matchhelp([F|E], [B|Phonemes], [T|Rules], [F|L],Originalstr) :-
    append(Beforechars,[F|E],Originalstr),
    reverse([F|E],K3),
    append(_,K2,K3),
    reverse(K2,K4),
    pattern(F,C,G,K4,none,B),
    suffix_match(G,Beforechars),
    T = F:C,
    append(K4,J,[F|E]),
    J = [],!,
    matchhelp(J, Phonemes, Rules, L, Originalstr).

matchhelp([F|E], [B|Phonemes], [T|Rules], [F|L],Originalstr) :-
    append(Beforechars,[F|E],Originalstr),
    reverse([F|E],K3),
    append(_,K2,K3),
    reverse(K2,K4),
    pattern(F,C,G,K4,any,B),
    suffix_match(G,Beforechars),!,
    T = F:C,
    append(K4,J,[F|E]),
    matchhelp(J, Phonemes, Rules, L, Originalstr).
    
matchhelp([F|E], [B|Phonemes], [T|Rules], [F|L],Originalstr) :-
    append(_,[F|E],Originalstr),
    reverse([F|E],K3),
    append(_,K2,K3),
    reverse(K2,K4),
    pattern(F,C,any,K4,A,B),
    prefix_match(A,E),!,
    T = F:C,
    append(K4,J,[F|E]),
    matchhelp(J, Phonemes, Rules, L, Originalstr).

matchhelp([F|E], [B|Phonemes], [T|Rules], [F|L],Originalstr) :-
    append(Beforechars,[F|E],Originalstr),
    reverse([F|E],K3),
    append(_,K2,K3),
    reverse(K2,K4),
    pattern(F,C,G,K4,A,B),
    prefix_match(A,E),
    suffix_match(G,Beforechars),!,
    T = F:C,
    append(K4,J,[F|E]),
    matchhelp(J, Phonemes, Rules, L, Originalstr).

matchhelp([F|E], [B|Phonemes], [T|Rules], [F|L],Originalstr) :-
    append(Beforechars,[F|E],Originalstr),
    reverse([F|E],K3),
    append(_,K2,K3),
    reverse(K2,K4),
    pattern(F,C,K4,K4,any,B),
    reverse(Beforechars,Z),
    startswith(K4,Z),!,
    T = F:C,
    append(K4,J,[F|E]),
    matchhelp(J, Phonemes, Rules, L, Originalstr).
    
matchhelp([F|E], [B|Phonemes], [T|Rules], [F|L],Originalstr) :-
    append(_,[F|E],Originalstr),
    reverse([F|E],K3),
    append(_,K2,K3),
    reverse(K2,K4),
    pattern(F,C,any,K4,any,B),!,
    T = F:C,
    append(K4,J,[F|E]),
    matchhelp(J, Phonemes, Rules, L, Originalstr).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                              tests
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

test(Chars) :-
   match(Chars, Phonemes, Rules), 
   write('Phonemes: '), write(Phonemes), nl, 
   write('Rules: '), write(Rules), nl.

t1 :- test([a,s,e,x,u,a,l]).
t2 :- test([t,h,i,m,b,l,e]).
t3 :- test([h,e,l,l,o,blank,t,h,e,r,e]).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                              main
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
load :-
   [match, sentence, phonemes].

talk(S, P) :-
   match(S,P,_).

list2string([],"").
list2string([A|R],R2) :-
   name(A,S),
   list2string(R,R1),
   append(S, " ", S1),
   append(S1,R1,R2).

play(P) :-
   list2string(P,P1),
   append("cd phonemes; java -cp .. play ", P1, P2),
   name(P3,P2),
   write('Executing: "'), write(P3), write('"'), nl,
   system(P3).

talk :-
   readsentence(S),
   talk(S,P),!,
   play(P).
   


